﻿using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using HappyBa.Core.Interfaces;
using HappyBa.Localization;
using Mnk.Library.Common.Log;
using Mnk.Library.Common.MT;

namespace HappyBa.Core.Data
{
    class DataReceiver : IDataReceiver
    {
        private readonly Config config;
        private readonly ITargetProccessFacade facade;
        private readonly ILog infoLog = LogManager.GetInfoLogger<DataReceiver>();

        public DataReceiver(Config config, ITargetProccessFacade facade)
        {
            this.config = config;
            this.facade = facade;
        }

        public ReceivedData Receive(IUpdater updater, IEnumerable<ProjectInfo> projects)
        {
            var connection = config.Settings.Connection;
            var sw = new Stopwatch();
            sw.Start();
            var data = new ReceivedData();
            Parallel.Invoke(
                () => data.Projects = facade.GetProjects(connection, projects),
                () => data.Roles = FilterAndSort(facade.GetRoles(connection)),
                () => data.EntityTypes = FilterAndSort(facade.GetEntityTypes(connection)),
                () => data.Bugs = facade.GetAllBugs(connection, projects),
                () => data.UserStories = facade.GetAllUserStories(connection, projects).Reverse().ToArray(),
                () => data.AllUsers = facade.GetAllUsers(connection).ToArray()
                );
            updater.Update(HappyBaLang.ReleasesCollected, 0.3f);
            var ids = data.UserStories.Select(x => x.Id)
                .ToArray();
            data.Tasks = facade.GetAllTasks(connection, ids);
            ids = ids.Concat(data.Tasks.Select(x => x.Id))
                .Concat(data.Bugs.Select(x => x.Id))
                .Concat(data.Impediments.Select(x => x.Id))
                .ToArray();
            updater.Update(HappyBaLang.ReleasesCollected, 0.5f);
            Parallel.Invoke(
                () => data.Impediments = facade.GetImpediments(connection, ids),
                () => data.Assignments = facade.GetAssigments(connection, ids),
                () => data.Comments = facade.GetComments(connection, ids),
                () => data.Times = facade.GetTimes(connection, ids)
                );
            updater.Update(HappyBaLang.ReleasesCollected, 1f);
            infoLog.Write("Receive data time:" + sw.Elapsed);
            return data;
        }

        private static IList<T> FilterAndSort<T>(IEnumerable<T> items)
            where T : NamedBase
        {
            return items.GroupBy(x => x.Name)
                .Select(x => x.First())
                .OrderBy(x => x.Name)
                .ToArray();
        }
    }

}
